package com.bytz.modules.cms.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bytz.common.exception.BytzBootException;
import com.bytz.common.system.query.QueryGenerator;
import com.bytz.common.util.PageUtils;
import com.bytz.modules.cms.c4c.model.C4cGetContacts;
import com.bytz.modules.cms.c4c.model.C4cResponse;
import com.bytz.modules.cms.c4c.sync.C4cOdataFeign;
import com.bytz.modules.cms.domain.manager.MallOrderProcessorManager;
import com.bytz.modules.cms.order.constant.OrderConstants;
import com.bytz.modules.cms.order.entity.Order;
import com.bytz.modules.cms.order.entity.OrderItem;
import com.bytz.modules.cms.order.model.OrderItemModel;
import com.bytz.modules.cms.order.model.OrderModel;
import com.bytz.modules.cms.order.service.IMallOrderService;
import com.bytz.modules.cms.order.util.OrderUtils;
import com.bytz.modules.cms.reseller.entity.EndUser;
import com.bytz.modules.cms.reseller.service.ICouponResellerService;
import com.bytz.modules.cms.reseller.service.IEndUserService;
import com.bytz.modules.cms.reseller.util.ResellerSecurityUtils;
import com.bytz.modules.cms.user.entity.EcAudit;
import com.bytz.modules.cms.user.service.IEcAuditService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 莱宝CMS—订单管理-订单主表 服务实现类
 * </p>
 *
 * @author KyleWang
 * @since 2022-10-10
 */
@Service
@Slf4j
public class MallOrderServiceImpl implements IMallOrderService {

    @Autowired
    private OrderServiceImpl orderService;

    @Autowired
    private OrderItemServiceImpl orderItemService;

    @Autowired
    private ICouponResellerService couponService;

    @Autowired
    private MallOrderProcessorManager orderProcessorManager;

    @Autowired
    private IEcAuditService ecAuditService;

    @Autowired
    private IEndUserService endUserService;

    @Autowired
    private C4cOdataFeign c4cOdataFeign;


    @Override
    public IPage<OrderModel> pageByReseller(OrderModel order, Page<Order> page, HttpServletRequest req) {

        String resellerId = ResellerSecurityUtils.getUserId();

        LambdaQueryWrapper<Order> wrapper = QueryGenerator.initLambdaQueryWrapper(order, req.getParameterMap(), Order.class)
                .eq(Order::getResellerId, resellerId)
                .orderByDesc(Order::getUpdateTime);

        Page<Order> orderPage = orderService.page(page, wrapper);

        return PageUtils.convertPage(orderPage, OrderModel.class, (out, in) -> {

            out.setCanEdit(StringUtils.equals(in.getStatus(), OrderConstants.OrderStatus.CAO_GAO));

            out.setCanPay(StringUtils.equals(in.getStatus(), OrderConstants.OrderStatus.DAI_YU_FU) ||
                    StringUtils.equals(in.getStatus(), OrderConstants.OrderStatus.YI_YU_FU) ||
                    StringUtils.equals(in.getStatus(), OrderConstants.OrderStatus.PAI_CHAN_ZHONG) ||
                    StringUtils.equals(in.getStatus(), OrderConstants.OrderStatus.DAI_TI_JIAO_WEI_KUAN));

            // e-chop自动签章的合同不为空，或者手动上传的合同不为空，都视为莱宝已盖章，手动上传的优先级更高
            boolean backendUploaded = (in.getEChopDocumentId() != null || in.getContractSignedFile() != null) &&
                    !OrderConstants.OrderStatus.DAI_GAI_ZHANG.equals(in.getStatus()) &&
                    !OrderConstants.OrderStatus.YI_ZHONG_ZHI.equals(in.getStatus());
            out.setCanDownloadContract(backendUploaded);

            boolean resellerUploaded = StringUtils.isNotBlank(in.getContractResellerFile());
            boolean orderComplete = OrderConstants.OrderStatus.YI_WAN_CHENG.equals(in.getStatus());
            out.setCanUploadContract(backendUploaded && !(resellerUploaded && orderComplete));

            boolean ecRequired = OrderUtils.ecRequired(in);
            boolean ecCanAudit = StringUtils.equals(in.getEcStatus(), OrderConstants.EcStatus.UNCOMMITTED) ||
                    StringUtils.equals(in.getEcStatus(), OrderConstants.EcStatus.REJECT);
            out.setCanAuditEc(ecRequired && ecCanAudit);
        });
    }

    @Override
    public OrderModel queryById(String id) {

        OrderModel result = new OrderModel();
        BeanUtils.copyProperties(orderService.getById(id), result);

        result.setOrderItemList(BeanUtil.copyToList(orderItemService.getByOrderId(id), OrderItemModel.class));

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderModel saveOrder(OrderModel model) {
        String resellerId = ResellerSecurityUtils.getUserId();
        orderProcessorManager.process(model, resellerId, false);

        doSaveOrder(model);

        return model;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @Lock4j(keys = {"T(com.bytz.modules.cms.reseller.util.ResellerSecurityUtils).getUserId()"})
    public OrderModel placeOrder(OrderModel model) {
        String resellerId = ResellerSecurityUtils.getUserId();
        orderProcessorManager.process(model, resellerId, true);

        // 保存
        doSaveOrder(model);

        if (StrUtil.isNotBlank(model.getCouponId())) {
            // 优惠券标记已使用
            couponService.markAsUsedById(model.getCouponId());
        }

        if (OrderConstants.EcStatus.UNCOMMITTED.equals(model.getEcStatus())) {
            initEc(model);
        }

        return model;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean submitEcAuditFile(OrderModel orderModel) {
        orderService.submitEcAuditFile(BeanUtil.copyProperties(orderModel, Order.class));
        ecAuditService.submitEcAuditFile(orderModel.getId());

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeById(String id) {
        Order order = orderService.getById(id);
        if (!OrderConstants.OrderStatus.CAO_GAO.equals(order.getStatus())) {
            throw new BytzBootException("该订单无法被删除");
        }
        orderItemService.removeByOrderId(id);
        return orderService.removeById(id);
    }

    @Override
    public Boolean uploadContract(OrderModel order) {
        return orderService.lambdaUpdate()
                .eq(Order::getId, order.getId())
                .set(Order::getContractResellerFile, order.getContractResellerFile())
                .set(Order::getStatus, OrderConstants.OrderStatus.DAI_YU_FU)
                .update();
    }

    /**
     * 保存订单到数据库
     */
    private void doSaveOrder(OrderModel model) {

        Order order = BeanUtil.toBean(model, Order.class);
        order.setSubmitPrepayRatio(order.getPrepayRatio());
        order.setSubmitTime(LocalDateTime.now());

        orderService.saveOrUpdate(order);

        List<OrderItem> mergeResult = orderItemService.mergeItem(
                order.getId(),
                BeanUtil.copyToList(model.getOrderItemList(), OrderItem.class)
        );

        model.setId(order.getId());
        model.setOrderItemList(BeanUtil.copyToList(mergeResult, OrderItemModel.class));
    }

    /**
     * 初始化EC审批数据
     */
    private void initEc(OrderModel order) {
        EcAudit ecAudit = new EcAudit();
        ecAudit.setOrderId(order.getId());

        ecAuditService.save(ecAudit);
    }


    /**
     * 根据shipToId从c4c中获取联系人
     * @param shipToId endUserId
     * @return C4cGetContacts
     */
    @Override
    public List<C4cGetContacts> getContactsByEndUserId(String shipToId) {
        try {
            // 根据shipToId获取endUser
            EndUser endUser = endUserService.getById(shipToId);
            if (BeanUtil.isEmpty(endUser)) {
                return Collections.emptyList();
            }
            // 获取联系人id
            String query = "AccountID eq '%s' and StatusCode eq '2'";
            C4cResponse<List<C4cGetContacts>> contacts = c4cOdataFeign.getContactCollection("ContactID,AccountID,Name,Email,Phone,Mobile", String.format(query, endUser.getAccountId()), "json");
            return contacts.getData().getResults();
        }catch (Exception e){
            log.error("获取c4c中的联系人失败，endUserId：" + shipToId, e);
            return Collections.emptyList();
        }

    }
}